iT邦幫忙

2023 iThome 鐵人賽

DAY 15
0
Modern Web

起步Go!Let's Go!系列 第 15

[ Day 15 ] Go 切片魔法:自由改變的程式碼旋律

  • 分享至 

  • xImage
  •  

在介紹陣列時,大家有沒有發現每次宣告陣列時都要去宣告長度,而且長度是宣告後就不能改變的。
接下來介紹一個比陣列更有彈性的組合型別-切片(slice)

原理

切片有三個部分組成:

  1. 陣列 ( Array )
  2. 長度 ( Length )
  3. 容量 ( Capacity )
package main
import "fmt"
func main(){
    role := [...]string{"董事長","總經理","副理","課長","一般員工"}
    slice := role[0:3]
    fmt.Println(slice)
    fmt.Println(role)        // Array
    fmt.Println(len(slice))  // Length
    fmt.Println(cap(slice))  // Capacity
}

執行結果:
[董事長 總經理 副理]
[董事長 總經理 副理 課長 一般員工]
3
5

第 4 行就是基本的宣告陣列的方式,來看第 5 行的 slice := role[0:3],這是甚麼意思?
它的意思是,我在 index = 0 的左邊切一刀,再到 index = 3 的左邊切一刀。
這樣 slice 就會從 role 中挑出 0, 1, 2 形成切片。
所以執行的結果才會是 [董事長 總經理 副理]

length 指的是 slice 過後的陣列長度,也就是 3
Capacity 指的是原本陣列 role 的長度,也就是 5

所以可以利用指向不同的陣列,可以實現容量、長度都可以變動的切片。

宣告一個有預設長度、容量的切片

除了直接從陣列切出來,也可以用 make 來宣告一個新的切片 slice
:::info
變數名稱 := make([]資料型態, length, capacity)
:::

package main
import "fmt"
func main(){
    slice := make([]sting, 3, 5)  // 變數名稱可以取自己喜歡的名字
    slice[0] = "董事長"
    slice[1] = "總經理"
    slice[2] = "副理"
    fmt.Println(slice)
    fmt.Println(len(slice))
    fmt.Println(cap(slice))
}

執行結果:
[董事長 總經理 副理]
3
5

第 4 行用 make 宣告新的切片,後面宣告切片型態,也就是 []string 或是 []int,接著,後面填入 lengthcapacity
第 9 行印出 slice 的長度 len,第 10 行印出 slice 的容量 cap

宣告一個長度與容量相同的切片

宣告時可以省略第 3 個參數 capacity,如果只有指定第 2 參數,那就代表宣告一個長度容量相同的 slice

package main
import "fmt"
func main(){
    slice := make([]string, 5)
    slice[0] = "董事長"
    slice[1] = "總經理"
    slice[2] = "副理"
    fmt.Println(slice)
    fmt.Println(len(slice))
    fmt.Println(cap(slice))
}

執行結果:
[董事長 總經理 副理]
5
5

快速宣告一個切片

除了可以用 make 宣告外,還可以用跟宣告陣列的方法來宣告。

package main
import "fmt"
func main(){
    slice := []string{"董事長","總經理","副理","課長"}
    fmt.Println(slice)
    fmt.Println(len(slice))
    fmt.Println(cap(slice))
}

執行結果:
[董事長 總經理 副理 課長]
4
4

:::warning
這邊要注意,在宣告切片時,是用 []string{}
宣告陣列時,適用 [...]string{}
:::

append()

宣告切片時,如果不確定要用多少容量,可以先宣告一個空切片,並且使用 append() 來插入新的值。
使用 append() 時,可以不考慮切片的容量,Go 會自己解決。

package main
import "fmt"
func main(){
    slice := []string{}    // 宣告空切片
    slice = append(slice, "董事長")
    slice = append(slice, "總經理")
    slice = append(slice, "副理")
    slice = append(slice, "課長")
    
    fmt.Println(slice)
    fmt.Println(len(slice))  // 長度
    fmt.Println(cap(slice))  // 容量 
}

執行結果:
[董事長 總經理 副理 課長]
4
4

巡迴切片

切片 ( slice ) 跟陣列一樣可以利用 for 進行走訪。

package main
import "fmt"
func main(){
    slice := []string{"董事長", "總經理", "副理", "課長"}
    for i := 0; i < len(slice); i ++{
        fmt.Printf("%d : %s\n", i, slice[i])
    }
}

執行結果:
0 : 董事長
1 : 總經理
2 : 副理
3 : 課長

slice 跟陣列一樣可以用 for range 進行巡迴切片,其規則跟走訪陣列一樣。

package main
import "fmt"
func main(){
    slice := []string{"董事長", "總經理", "副理", "課長"}
    for k, v := range slice{
        fmt.Printf("%d : %s\n", k, v)
    }
}

執行結果:
0 : 董事長
1 : 總經理
2 : 副理
3 : 課長


上一篇
[ Day 14 ] Go 陣列:創建、賦能、巡禮
下一篇
[ Day 16] Go 映射 (Map) :鍵值之間的奇幻冒險
系列文
起步Go!Let's Go!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言